import __builtin__
from client.towersystem import testtower, hightower, fattower
from panda3d.core import Texture, TextureStage, Point3, BitMask32, Vec3, VBase3
from pandac.PandaModules import TransparencyAttrib
from client.utils import assethandling
from client.utils.postring import Postring
import database.towers
import database.projectiles


class TowerManager():
    def __init__(self, game):
        self.towerNode = __builtin__.render.attachNewNode("Tower Node")
        self.projNode = __builtin__.render.attachNewNode("Projectile Node")
        self.placedTowers = []
        self.projectiles = []
        self.canPlace = True
        self.game = game
        self.towerCursor = None
        self.curTower = None

    def request_selection(self, pos):
        enc = __builtin__.base.gamestatemanager.getState("RunningSession").prep_msg("select")
        enc.write_float(pos[0])
        enc.write_float(pos[1])
        __builtin__.base.gamestatemanager.getState("RunningSession").send_message(enc.get_message())

    def request_upgrade(self, tower, x):
        index = self.placedTowers.index(tower)
        enc = __builtin__.base.gamestatemanager.getState("RunningSession").prep_msg("upgrade")
        enc.write_int(index)
        enc.write_int(x)
        __builtin__.base.gamestatemanager.getState("RunningSession").send_message(enc.get_message())

    def upgrade(self, ind, x):
        old = self.placedTowers[ind]
        tnew = database.towers.get_tower_data(old.upgrades[x])
        self.game.select_tower(self.build_tower(old.upgrades[x], old.towerNode.getPos()))
        self.destroy_tower(old)

    def activate(self):
        self.towerNode = __builtin__.render.attachNewNode("Tower Node")
        self.projNode = __builtin__.render.attachNewNode("Projectile Node")
        self.towerCursor = assethandling.createTower()
        self.towerCursor.setTransparency(TransparencyAttrib.MAlpha)
        self.towerCursor.detachNode()

    def deactivate(self):
        self.destroy_towers()
        self.remove_all_projectiles()
        self.towerNode.removeNode()
        self.projNode.removeNode()
        self.towerCursor.removeNode()

    def update(self, dt):
        # iterate over all towers and units and get nearest tower in range
        #self.check_tower_positions()
        #self.update_tower_color()
        for p in self.projectiles:
            p.update(dt)

    def request_tower_placement(self, pos):
        name = self.curTower.name
        enc = __builtin__.base.gamestatemanager.getState("RunningSession").prep_msg("place_tower")
        enc.write_string(name)
        enc.write_float(pos[0])
        enc.write_float(pos[1])

        __builtin__.base.gamestatemanager.getState("RunningSession").send_message(enc.get_message())

    def place_tower(self, name, pos):
        self.game.select_tower(self.build_tower(name, pos))
        self.game.canBuild = 0
        self.remove_cursor()

            #print("Placed " + t.name + " at " + str(t.towerNode.getPos()))

    def build_tower(self, name, pos):
        t = database.towers.create_tower(name)
        t.towerNode.reparentTo(self.towerNode)
        t.towerNode.setPos(Vec3(pos[0], pos[1], 0.06))
        self.placedTowers.append(t)
        return t

    def shoot_projectile(self, name, pos, target, index):
        tar = None
        if target == "unit":
            tar = __builtin__.base.gamestatemanager.getState("RunningSession").unitmanager.units[index]
        elif target == "tower":
            tar = self.placedTowers[index]
        if tar is None:
            return
        p = database.projectiles.create_projectile(name, tar, self)
        p.set_pos(Vec3(pos[0], pos[1], 1))
        p.projectileNode.reparentTo(self.projNode)
        self.projectiles.append(p)

    def update_projectiles(self, positions):
        for p in self.projectiles:
            ppos = positions[self.projectiles.index(p)]
            p.set_pos(Vec3(ppos[0], ppos[1], 0.5))

    def remove_projectile(self, ind):
        p = self.projectiles[ind]
        self.projectiles.remove(p)
        p.destroy()
        del p

    def destroy_projectile(self, p):
        self.projectiles.remove(p)
        p.destroy()
        del p

    def update_mouse(self, x, y, z):
        self.towerCursor.setPos(x, y, z)

    def check_tower_positions(self):
        self.canPlace = True
        if VBase3.length(self.towerCursor.getPos()) > 12 or VBase3.length(self.towerCursor.getPos()) < 2.8:
            self.canPlace = False
            self.update_tower_color()
            return
        for t in self.placedTowers:
            ghost = t.towerNode.find("TowerGhost").node()
            for n in ghost.getOverlappingNodes():
                if n == self.towerCursor.find("TowerGhost").node():
                    self.canPlace = False
                    self.update_tower_color()
                    return
        self.update_tower_color()

    def update_tower_color(self):
        if self.canPlace and self.game.curMoney >= 5:
            self.towerCursor.setColor(1, 1, 1, 0.5)
        else:
            self.towerCursor.setColor(1, 0, 0, 0.75)

    def destroy_towers(self):
        for t in self.placedTowers:
            t.towerNode.remove_node()
        self.placedTowers =[]

    def remove_all_projectiles(self):
        for i in range(len(self.projectiles)-1, -1, -1):
            self.remove_projectile(i)
        self.projectiles = []

    def fight(self):
        self.towerCursor.detachNode()

    def prepare_cursor(self, name):
        if self.towerCursor is not None:
            self.towerCursor.remove_node()
        self.towerCursor = assethandling.createTower()
        self.curTower = database.towers.get_tower_data(name)
        self.towerCursor.reparentTo(__builtin__.render)

    def remove_cursor(self):
        self.towerCursor.detachNode()
        self.curTower = None

    def destroy_tower(self, tower):
        self.placedTowers.remove(tower)
        tower.destroy()

    def prepare(self):
        #self.tower.reparentTo(__builtin__.render)
        return